package com.test33_反射;

import org.junit.Test;
import sun.misc.Unsafe;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Unsafe工具类
 * 可以在没有实例化对象的情况下，进行类中方法的调用
 */
public class Demo09_Unsafe {

    /**
     * 获取Unsafe对象
     */
    @Test
    public void test1() throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);    // 取消封装
        Unsafe unsafe = (Unsafe) unsafeField.get(null);     // 获取Unsafe对象
        System.out.println(unsafe);
    }

    /**
     * 通过反射调用方法
     */
    @Test
    public void test2() throws Exception {
        Class<?> clazz = Class.forName("com.test33_反射.Singleton9");
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        Object object = constructor.newInstance();
        Method printMethod = clazz.getMethod("print");
        printMethod.invoke(object);
    }

    /**
     * 通过Unsafe类绕过JVM的对象管理机制实现方法调用
     */
    @Test
    public void test3() throws Exception {
        Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
        unsafeField.setAccessible(true);    // 取消封装
        Unsafe unsafe = (Unsafe) unsafeField.get(null);     // 获取Unsafe对象
        Singleton9 singleton = (Singleton9) unsafe.allocateInstance(Singleton9.class);  // 获取类对象实例
        singleton.print();  // 直接实现方法调用，连实例化对象的操作都省了
    }
}

class Singleton9 {
    private Singleton9() {
        System.out.println("【Singleton】实例化类对象");
    }

    public void print() {
        System.out.println("李兴华编程训练营：yootk.ke.qq.com");
    }
}
